home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / JFC.bin / MacComboBoxUI.java < prev    next >
Text File  |  1998-06-30  |  19KB  |  730 lines

  1. /*
  2.  * @(#)MacComboBoxUI.java    1.6 98/02/02
  3.  *
  4.  * Copyright (c) 1998 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  *
  19.  */
  20.  
  21. package com.sun.java.swing.plaf.mac;
  22.  
  23. import java.awt.*;
  24. import java.awt.event.*;
  25. import java.io.Serializable;
  26.  
  27. import com.sun.java.swing.*;
  28. import com.sun.java.swing.plaf.*;
  29. import com.sun.java.swing.border.*;
  30.  
  31.  
  32. /**
  33.  * ComboBox mac look and feel
  34.  * <p>
  35.  * Warning: serialized objects of this class will not be compatible with
  36.  * future swing releases.  The current serialization support is appropriate
  37.  * for short term storage or RMI between Swing1.0 applications.  It will
  38.  * not be possible to load serialized Swing1.0 objects with future releases
  39.  * of Swing.  The JDK1.2 release of Swing will be the compatibility
  40.  * baseline for the serialized form of Swing objects.
  41.  *
  42.  * @version @(#)MacComboBoxUI.java    1.0 01/20/98
  43.  * @author Symantec
  44.  */
  45. public class MacComboBoxUI extends ComboBoxUI implements Serializable
  46. {
  47.     static Color pressedBackground = UIManager.getColor("Control.pressedBackground");
  48.     static Color pressedForeground = UIManager.getColor("Control.pressedForeground");
  49.  
  50.     static Color disabledBackground = UIManager.getColor("Control.disabledBackground");
  51.     static Color disabledForeground = UIManager.getColor("Control.disabledForeground");
  52.  
  53.     static Color enabledBackground = UIManager.getColor("MenuItem.background");
  54.     
  55.     static Dimension defaultSize = new Dimension(100, 20);
  56.  
  57.     protected JComboBox comboBox = null;
  58.     protected CellRendererPane currentValuePane = new CellRendererPane();
  59.     protected JButton arrowButton;
  60.     protected Component editor;
  61.     protected JPopupMenu menu = null;
  62.     protected JList listBox = null;
  63.     protected ActionListener actionListener = new ComboBoxMenuItemListener();
  64.     protected MouseListener mouseListener = new ComboBoxMouseListener();
  65.     protected ItemListener itemListener = new ComboBoxItemListener();
  66.  
  67.  
  68.         /*
  69.          *
  70.          *    ComponentUI methods
  71.          *
  72.          */
  73.  
  74.     public static ComponentUI createUI(JComponent c) {
  75.         return new MacComboBoxUI();
  76.     }
  77.  
  78.     public void installUI(JComponent c) {
  79.         comboBox = (JComboBox) c;
  80.  
  81.         arrowButton = new JButton(MacMenuUtilities.getComboBoxPopupArrowIcon()) {
  82.             {
  83.                 setModel(new ComboBoxButtonModel());
  84.                 setMargin(new Insets(2, 2, 2, 2/*1, 3*/));
  85.                 setRequestFocusEnabled(false);
  86.             }
  87.         };
  88.         arrowButton.addMouseListener(mouseListener);
  89.         comboBox.add(arrowButton);
  90.  
  91.         comboBox.add(currentValuePane);
  92.         comboBox.setLayout(new ComboBoxLayout());
  93.  
  94.         comboBox.addItemListener(itemListener);
  95.         comboBox.addMouseListener(mouseListener);
  96.  
  97.         if (comboBox.getRenderer() == null)
  98.             comboBox.setRenderer((ListCellRenderer)(UIManager.get("ComboBox.renderer")));
  99.  
  100.         LookAndFeel.installColorsAndFont(comboBox,"ComboBox.background","ComboBox.foreground",
  101.                                                 "ComboBox.font");
  102.         editablePropertyChanged();
  103.  
  104.         c.setRequestFocusEnabled(false);
  105.     }
  106.  
  107.     public void uninstallUI(JComponent c) {
  108.         hidePopup();
  109.         removeEditor();
  110.  
  111.         if (arrowButton != null) {
  112.             comboBox.remove(arrowButton);
  113.             arrowButton.removeMouseListener(mouseListener);
  114.             arrowButton = null;
  115.         }
  116.  
  117.         comboBox.setLayout(null);
  118.  
  119.         comboBox.removeItemListener(itemListener);
  120.         comboBox.removeMouseListener(mouseListener);
  121.  
  122.         comboBox.remove(currentValuePane);
  123.  
  124.         if (comboBox.getRenderer() instanceof UIResource)
  125.             comboBox.setRenderer(null);
  126.  
  127.         if (comboBox.getEditor() instanceof UIResource)
  128.             comboBox.setEditor(null);
  129.  
  130.         if (comboBox.getBorder() instanceof UIResource)
  131.             comboBox.setBorder(null);
  132.  
  133.         comboBox = null;
  134.     }
  135.  
  136.     public void paint(Graphics g, JComponent c) {
  137.         if (!comboBox.isEditable()) {
  138.             Rectangle bounds = rectangleForCurrentValue();
  139.  
  140.             Color t = g.getColor();
  141.  
  142.             Color bgColor;
  143.             Color fgColor;
  144.             if (popupIsVisible()) {
  145.                 bgColor = pressedBackground;
  146.                 fgColor = pressedForeground;
  147.             }
  148.             else if (c.isEnabled()) {
  149.                 bgColor = enabledBackground;
  150.                 fgColor = comboBox.getForeground();
  151.             }
  152.             else {
  153.                 bgColor = disabledBackground;
  154.                 fgColor = disabledForeground;
  155.             }
  156.  
  157.             g.setColor(bgColor);
  158.             g.fillRect(bounds.x,bounds.y,bounds.width,bounds.height);
  159.             g.setColor(t);
  160.  
  161.             ListCellRenderer renderer = comboBox.getRenderer();
  162.  
  163.             validateList();
  164.  
  165.             listBox.setFont(comboBox.getFont());
  166.             listBox.setForeground(fgColor);
  167.             listBox.setBackground(bgColor);
  168.             Component rendererComponent = renderer.getListCellRendererComponent(listBox, comboBox.getSelectedItem(), -1, false, false);
  169.  
  170.             // Just in case!
  171.             rendererComponent.setFont(comboBox.getFont());
  172.             rendererComponent.setForeground(fgColor);
  173.             rendererComponent.setBackground(bgColor);
  174.  
  175.             currentValuePane.paintComponent(g, rendererComponent, comboBox, bounds);
  176.         }
  177.     }
  178.  
  179.     public Dimension getPreferredSize(JComponent c) {
  180.         validateList();
  181.  
  182.         Dimension preferredSize = new Dimension();
  183.         Dimension testSize;
  184.         ListCellRenderer renderer = comboBox.getRenderer();
  185.         ComboBoxModel model = comboBox.getModel();
  186.  
  187.         if (renderer != null && model.getSize() > 0) {
  188.             for (int i = 0, numElements = model.getSize(); i < numElements; i++) {
  189.                 Component cpn = renderer.getListCellRendererComponent(listBox, model.getElementAt(i), -1, false, false);
  190.  
  191.                 currentValuePane.add(cpn);
  192.                 cpn.setFont(comboBox.getFont());
  193.                 testSize = cpn.getPreferredSize();
  194.                 currentValuePane.remove(cpn);
  195.  
  196.                 preferredSize.width = Math.max(preferredSize.width, testSize.width);
  197.                 preferredSize.height = Math.max(preferredSize.height, testSize.height);
  198.             }
  199.  
  200.             if (comboBox.isEditable()) {
  201.                 testSize = editor.getPreferredSize();
  202.                 preferredSize.width = Math.max(preferredSize.width, testSize.width);
  203.                 preferredSize.height = Math.max(preferredSize.height, testSize.height);
  204.             }
  205.         } else {
  206.             preferredSize.width = defaultSize.width;
  207.             preferredSize.height = defaultSize.height;
  208.         }
  209.  
  210.         if (arrowButton != null) {
  211.             testSize = arrowButton.getPreferredSize();
  212.  
  213.             preferredSize.width += testSize.width;
  214.             preferredSize.height = Math.max(preferredSize.height, testSize.height);
  215.         }
  216.  
  217.         return preferredSize;
  218.     }
  219.  
  220.     public Dimension getMinimumSize(JComponent c) {
  221.         validateList();
  222.  
  223.         Dimension minimumSize = new Dimension();
  224.         Dimension testSize;
  225.         ListCellRenderer renderer = comboBox.getRenderer();
  226.         ComboBoxModel model = comboBox.getModel();
  227.  
  228.         if (renderer != null && model.getSize() > 0) {
  229.             for (int i = 0, numElements = model.getSize(); i < numElements; i++) {
  230.                 Component cpn = renderer.getListCellRendererComponent(listBox, model.getElementAt(i), -1, false, false);
  231.  
  232.                 currentValuePane.add(cpn);
  233.                 cpn.setFont(comboBox.getFont());
  234.                 testSize = cpn.getMinimumSize();
  235.                 currentValuePane.remove(cpn);
  236.  
  237.                 minimumSize.width = Math.max(minimumSize.width, testSize.width);
  238.                 minimumSize.height = Math.max(minimumSize.height, testSize.height);
  239.             }
  240.  
  241.             if (comboBox.isEditable()) {
  242.                 testSize = editor.getMinimumSize();
  243.                 minimumSize.width = Math.max(minimumSize.width, testSize.width);
  244.                 minimumSize.height = Math.max(minimumSize.height, testSize.height);
  245.             }
  246.         } else {
  247.             minimumSize.width = defaultSize.width;
  248.             minimumSize.height = defaultSize.height;
  249.         }
  250.  
  251.         if (arrowButton != null) {
  252.             testSize = arrowButton.getMinimumSize();
  253.  
  254.             minimumSize.width += testSize.width;
  255.             minimumSize.height = Math.max(minimumSize.height, testSize.height);
  256.         }
  257.  
  258.         return minimumSize;
  259.     }
  260.  
  261.     public Dimension getMaximumSize(JComponent c) {
  262.         validateList();
  263.  
  264.         Dimension maximumSize = new Dimension();
  265.         Dimension testSize;
  266.         ListCellRenderer renderer = comboBox.getRenderer();
  267.         ComboBoxModel model = comboBox.getModel();
  268.  
  269.         if (renderer != null && model.getSize() > 0) {
  270.             for (int i = 0, numElements = model.getSize(); i < numElements; i++) {
  271.                 Component cpn = renderer.getListCellRendererComponent(listBox, model.getElementAt(i), -1, false, false);
  272.  
  273.                 currentValuePane.add(cpn);
  274.                 cpn.setFont(comboBox.getFont());
  275.                 testSize = cpn.getMinimumSize();
  276.                 currentValuePane.remove(cpn);
  277.  
  278.                 maximumSize.height = Math.max(maximumSize.height, testSize.height);
  279.             }
  280.  
  281.             if (comboBox.isEditable()) {
  282.                 testSize = editor.getMaximumSize();
  283.                 maximumSize.height = Math.max(maximumSize.height, testSize.height);
  284.             }
  285.         } else {
  286.             maximumSize.height = defaultSize.height;
  287.         }
  288.  
  289.         if (arrowButton != null) {
  290.             testSize = arrowButton.getMaximumSize();
  291.  
  292.             maximumSize.height = Math.max(maximumSize.height, testSize.height);
  293.         }
  294.         maximumSize.width = Short.MAX_VALUE;
  295.  
  296.         return maximumSize;
  297.     }
  298.  
  299.  
  300.  
  301.         /*
  302.          *
  303.          *    ComboBoxUI methods
  304.          *
  305.          */
  306.  
  307.     /** This method is called when the maximum number of rows is changing **/
  308.     public void maximumRowCountChanged() {
  309.         if (popupIsVisible()) {
  310.             hidePopup();
  311.             showPopup();
  312.         }
  313.     }
  314.     
  315.     /** This method is called when the editable property changes. **/
  316.     public void editablePropertyChanged() {
  317.         if (comboBox.isEditable())
  318.             addEditor();
  319.         else
  320.             removeEditor();
  321.     }
  322.  
  323.     /** This method is called when the enabled property changes **/
  324.     public void enablePropertyChanged() {
  325.         if (comboBox.isEnabled()) {
  326.             if (editor != null) 
  327.                 editor.setEnabled(true);
  328.             if (arrowButton != null)
  329.                 arrowButton.setEnabled(true);
  330.         } else {
  331.             if (editor != null)
  332.                 editor.setEnabled(false);
  333.             if (arrowButton != null)
  334.                 arrowButton.setEnabled(false);
  335.         }
  336.         comboBox.repaint();
  337.     }
  338.  
  339.     /** This method request the UI to show the popup **/
  340.     public void showPopup() {
  341.         validateMenu();
  342.         validateList();
  343.  
  344.         Point menuPt;
  345.         if (comboBox.isEditable() && arrowButton != null) {
  346.             menuPt = arrowButton.getLocation();
  347.         } else {
  348.             menuPt = new Point(0, 0);
  349.         }
  350.  
  351.         int selectedIndex = comboBox.getSelectedIndex();
  352.  
  353.         menu.show(comboBox,menuPt.x, menuPt.y);
  354.         menu.requestFocus();
  355.         
  356.         comboBox.repaint();
  357.  
  358.         MenuElement me[];
  359.         if (selectedIndex >= 0) {
  360.             me = new MenuElement[2];
  361.             me[1] = (MenuElement) menu.getComponentAtIndex(selectedIndex);
  362.         } else {
  363.             me = new MenuElement[1];
  364.         }
  365.         me[0] = menu;
  366.         MenuSelectionManager.defaultManager().setSelectedPath(me);
  367.     }
  368.  
  369.     /** This method request the UI to hide the popup **/
  370.     public void hidePopup() {
  371.         if (!popupIsVisible())
  372.             return;
  373.  
  374.         menu.setVisible(false);
  375.  
  376.         comboBox.repaint();
  377.  
  378.         if (comboBox.isEditable())
  379.             editor.requestFocus();
  380.  
  381.         resetMenu();
  382.     }
  383.  
  384.     /** This method determines if the popup is visible **/
  385.     public boolean popupIsVisible() {
  386.         if (menu == null)
  387.             return false;
  388.         else
  389.             return menu.isVisible();
  390.     }
  391.  
  392.     /** This method determines whether or not the combo box itself is traversable **/
  393.     public boolean isFocusTraversable() {
  394.         return false;
  395.     }
  396.  
  397.     /** 
  398.      * This method asks the UI for the JList is using to display the
  399.      * contents of the ComboBox.  The return value is meant to be used
  400.      * for read-only values -- any modification to the JList is 
  401.      * unsupported.
  402.      */
  403.     public JList getList() {
  404.         return listBox;
  405.     }
  406.  
  407.  
  408.  
  409.     
  410.     void addEditor() {
  411.         if (comboBox.getBorder() instanceof UIResource)
  412.             comboBox.setBorder(null);
  413.  
  414.         if (arrowButton != null)
  415.             arrowButton.setBorder(MacBorderFactory.getEditableComboBoxArrowBorder());
  416.  
  417.         if (editor != null) {
  418.             comboBox.remove(editor);
  419.             editor = null;
  420.         }
  421.         if (comboBox.getEditor() == null)
  422.             comboBox.setEditor((ComboBoxEditor) (UIManager.get("ComboBox.editor")));
  423.         editor = comboBox.getEditor().getEditorComponent();
  424.         comboBox.add(editor);
  425.         editor.setFont(comboBox.getFont());
  426.         comboBox.configureEditor(comboBox.getEditor(),comboBox.getSelectedItem());
  427.     }
  428.  
  429.     void removeEditor() {
  430.         if (editor != null) {
  431.             comboBox.remove(editor);
  432.             editor = null;
  433.         }
  434.  
  435.         if (comboBox.getBorder() == null || comboBox.getBorder() instanceof UIResource)
  436.             comboBox.setBorder(MacBorderFactory.getComboBoxBorder());
  437.  
  438.         if (arrowButton != null)
  439.             arrowButton.setBorder(MacBorderFactory.getComboBoxArrowBorder());
  440.     }
  441.  
  442.     Rectangle rectangleForCurrentValue() {
  443.         Dimension cbSize = comboBox.getSize();
  444.         Insets insets = comboBox.getInsets();
  445.  
  446.         Rectangle r = new Rectangle(insets.left, insets.top, cbSize.width - insets.left, cbSize.height - (insets.top + insets.bottom));
  447.         if (arrowButton != null)
  448.             r.width -= arrowButton.getSize().width;
  449.         else
  450.             r.width -= insets.right;
  451.  
  452.         return r;
  453.     }
  454.  
  455.  
  456.     void validateMenu() {
  457.         if (menu == null) {
  458.             // Create the popup menu and populate it with items
  459.             menu = new JPopupMenu();
  460.             menu.addPopupMenuListener(new ComboBoxRepaintRequester());
  461.             menu.setDoubleBuffered(true);
  462.             menu.setInvoker(comboBox);
  463.         } else {
  464.             resetMenu();
  465.         }
  466.  
  467.         int numItems = comboBox.getModel().getSize();
  468.         for (int anItem = 0; anItem < numItems; anItem++) {
  469.             JMenuItem mi = menu.add(new ComboBoxMenuItem(anItem));
  470.             mi.addActionListener(actionListener);
  471.         }
  472.     }
  473.  
  474.             // Combo box implementations expect a listBox, so we need to create one
  475.     void validateList() {
  476.         if (listBox == null) {
  477.             listBox = new JList(comboBox.getModel());
  478.             listBox.setCellRenderer(comboBox.getRenderer());
  479.         }
  480.     }
  481.  
  482.     void resetMenu() {
  483.         MenuSelectionManager.defaultManager().clearSelectedPath();
  484.  
  485.         Component[] components = menu.getComponents();
  486.         int numItems = components.length;
  487.         if (numItems > 0) {
  488.             for (int anItem = 0; anItem < numItems; anItem++) {
  489.                 JMenuItem mi = (JMenuItem) components[anItem];
  490.                 mi.removeActionListener(actionListener);
  491.             }
  492.             menu.removeAll();
  493.         }
  494.     }
  495.  
  496.  
  497.         /*
  498.          *
  499.          *    MouseListener methods
  500.          *
  501.          */
  502.     class ComboBoxMouseListener extends MouseAdapter {
  503.  
  504.         /**
  505.          * Invoked when a mouse button has been pressed on a component.
  506.          */
  507.         public void mousePressed(MouseEvent e) {
  508.             if (!comboBox.isEnabled())
  509.                 return;
  510.     
  511.             if (popupIsVisible()) {
  512.                 hidePopup();
  513.             } else {
  514.                 showPopup();
  515.             }
  516.         }
  517.  
  518.         /**
  519.          * Invoked when a mouse button has been released on a component.
  520.          */
  521.         public void mouseReleased(MouseEvent e) {
  522.             if (popupIsVisible())
  523.                 MenuSelectionManager.defaultManager().processMouseEvent(e);
  524.         }
  525.     
  526.         /**
  527.          * Invoked when the mouse enters a component.
  528.          */
  529.         public void mouseEntered(MouseEvent e) {
  530.             if (popupIsVisible())
  531.                 MenuSelectionManager.defaultManager().processMouseEvent(e);
  532.         }
  533.     
  534.         /**
  535.          * Invoked when the mouse exits a component.
  536.          */
  537.         public void mouseExited(MouseEvent e) {
  538.             if (popupIsVisible())
  539.                 MenuSelectionManager.defaultManager().processMouseEvent(e);
  540.         }
  541.     }
  542.  
  543.  
  544.         /*
  545.          *
  546.          *    MouseListener methods
  547.          *
  548.          */
  549.  
  550.     class ComboBoxItemListener implements ItemListener {
  551.  
  552.         /**
  553.          * Invoked when an item's state has been changed.
  554.          */    
  555.         public void itemStateChanged(ItemEvent e) {
  556.             Object v = comboBox.getModel().getSelectedItem();
  557.  
  558.             if(editor != null) {
  559.                 comboBox.configureEditor(comboBox.getEditor(),v);
  560.             } else {
  561.                 comboBox.repaint(rectangleForCurrentValue());
  562.             }
  563.         }
  564.     }
  565.  
  566.         /*
  567.          *
  568.          *    MouseListener methods
  569.          *
  570.          */
  571.  
  572.     class ComboBoxMenuItemListener implements ActionListener {
  573.  
  574.         /**
  575.          * Invoked when a menu item is selected.
  576.          */
  577.         public void actionPerformed(ActionEvent e) {
  578.             comboBox.setSelectedIndex(((ComboBoxMenuItem) e.getSource()).getItemIndex());
  579.         }
  580.     }
  581.  
  582.     
  583.         /*
  584.          *
  585.          *    LayoutManager methods
  586.          *
  587.          */
  588.     
  589.     class ComboBoxLayout implements LayoutManager {
  590.     
  591.         /**
  592.          * Adds the specified component with the specified name to
  593.          * the layout.
  594.          * @param name the component name
  595.          * @param comp the component to be added
  596.          */
  597.         public void addLayoutComponent(String name, Component comp) {}
  598.     
  599.         /**
  600.          * Removes the specified component from the layout.
  601.          * @param comp the component ot be removed
  602.          */
  603.         public void removeLayoutComponent(Component comp) {}
  604.     
  605.         /**
  606.          * Calculates the preferred size dimensions for the specified 
  607.          * panel given the components in the specified parent container.
  608.          * @param parent the component to be laid out
  609.          *  
  610.          * @see #minimumLayoutSize
  611.          */
  612.         public Dimension preferredLayoutSize(Container parent) {
  613.             return ((JComboBox)parent).getPreferredSize();
  614.         }
  615.     
  616.         /** 
  617.          * Calculates the minimum size dimensions for the specified 
  618.          * panel given the components in the specified parent container.
  619.          * @param parent the component to be laid out
  620.          * @see #preferredLayoutSize
  621.          */
  622.         public Dimension minimumLayoutSize(Container parent) {
  623.             return ((JComboBox)parent).getMinimumSize();
  624.         }
  625.     
  626.         /** 
  627.          * Lays out the container in the specified panel.
  628.          * @param parent the component which needs to be laid out 
  629.          */
  630.         public void layoutContainer(Container parent) {
  631.             if (arrowButton != null) {
  632.                 Dimension cbSize = comboBox.getSize();
  633.                 Dimension arrowSize = arrowButton.getPreferredSize();
  634.     
  635.                 if (comboBox.isEditable()) {
  636.                     arrowButton.setBounds(cbSize.width - arrowSize.width, (cbSize.height - arrowSize.height)/2, arrowSize.width, arrowSize.height);
  637.                 } else {
  638.                     arrowButton.setBounds(cbSize.width - arrowSize.width, 0, arrowSize.width, cbSize.height);
  639.                 }
  640.             }
  641.     
  642.             if (editor != null) {
  643.                 editor.setBounds(rectangleForCurrentValue());
  644.             }
  645.         }
  646.     }
  647.     
  648.     class ComboBoxMenuItem extends JMenuItem {
  649.         int itemIndex;
  650.         
  651.         public ComboBoxMenuItem(int menuItem) {
  652.             super();
  653.             itemIndex = menuItem;
  654.         }
  655.         JComboBox getComboBox() {
  656.             return comboBox;
  657.         }
  658.         int getItemIndex() {
  659.             return itemIndex;
  660.         }
  661.  
  662.  
  663.         /**
  664.          * Returns the name of the L&F class that renders this component.
  665.          *
  666.          * @return "ComboBoxMenuItemUI"
  667.          * @see JComponent#getUIClassID
  668.          * @see UIDefaults#getUI
  669.          */
  670.         public String getUIClassID() {
  671.             return "ComboBoxMenuItemUI";
  672.         }
  673.     }
  674.  
  675.     class ComboBoxRepaintRequester implements ActionListener, com.sun.java.swing.event.PopupMenuListener {
  676.         Timer timer = null;
  677.  
  678.         ComboBoxRepaintRequester() {
  679.         }
  680.  
  681.         /**
  682.          *  This method is called before the popup menu becomes visible 
  683.          */
  684.         public void popupMenuWillBecomeVisible(com.sun.java.swing.event.PopupMenuEvent e) {}
  685.  
  686.         /**
  687.          * This method is called before the popup menu becomes invisible
  688.          * Note that a JPopupMenu can become invisible any time 
  689.          */
  690.         public void popupMenuWillBecomeInvisible(com.sun.java.swing.event.PopupMenuEvent e) {
  691.             startTimer();
  692.         }
  693.  
  694.         /**
  695.          * This method is called when the popup menu is canceled
  696.          */
  697.         public void popupMenuCanceled(com.sun.java.swing.event.PopupMenuEvent e) {}
  698.         
  699.         private void startTimer() {
  700.             timer = new Timer(200,this);
  701.             timer.start();
  702.         }
  703.  
  704.         public void actionPerformed(ActionEvent e) {
  705.             if (timer != null) {
  706.                 timer.stop();
  707.                 timer = null;
  708.             }
  709.             comboBox.repaint();
  710.         }
  711.     }
  712.  
  713.     class ComboBoxButtonModel extends DefaultButtonModel {
  714.         /**
  715.          * Checks if the button is armed.
  716.          */
  717.         public boolean isArmed() {
  718.             return super.isArmed() || popupIsVisible();
  719.         }
  720.  
  721.         /**
  722.          * Checks if the button is pressed.
  723.          */
  724.         public boolean isPressed() {
  725.             return super.isPressed() || popupIsVisible();
  726.         }
  727.     }
  728.  
  729. }
  730.